#include <iostream>
#include <string>
#include <string.h>
#include <vector>
#include <time.h>
#include <stdint.h>
#include <map>
#include <algorithm>
#include <memory>

#define SETC_COLPOI(c, p) ((p << 4) + c)
#define GETC_COLOR(v) (v & 0xf)
#define GETC_POINT(v) ((v >> 4) & 0xf)
#define GETC_REALPOINT(v) (((v >> 4) & 0xf) > 10 ? 10 : (v) & 0xf)
#define NUM 5
#define TOTAL  52
#define A

#ifdef A
std::vector<uint16_t *> CardCombin; //牌的组合
#endif

#ifndef A
std::vector<std::vector<uint32_t > > CardCombin;
#endif

uint32_t a[NUM];
using namespace std;
//递归算法
// void comb(uint32_t m, uint32_t k)
// {
//     //a[0] = NUM;
//     uint32_t i, j;
//     for (i = m; i >= k; i--)
//     {
//         a[k] = i;
//         if (k > 1)
//             comb(i - 1, k - 1);
//         else
//         {
// #ifdef A
//             uint32_t *combin = new uint32_t(3);
// #endif

// #ifndef A
//             std::vector<uint32_t> combin;
// #endif

//             for (j = a[0]; j > 0; j--)
//             {
//                //std::cout << a[j] << "\t";
// #ifdef A
//                combin[j-1] = a[j];
// #endif
// #ifndef A
//                combin.push_back(a[j]);
// #endif
//               }
//             // std::cout << std::endl;
//              CardCombin.push_back(combin);
//         }
//     }
// }

//数组算法
template <typename T>
void Combine(std::vector<T> &data, uint16_t n, uint16_t m)
{
    if (m > n)
        return;

    uint16_t *pTable = new uint16_t[n]; //定义标记buf并将其前m个置1
    memset(pTable, 0, sizeof(uint16_t) * n);
    for (uint16_t i = 0; i < m; ++i)
        pTable[i] = 1;

    bool bFind = false;
    do
    {   uint16_t k = 0;
        uint16_t *combin = new uint16_t(5); //存储每组牌（五张）
        for (uint16_t i = 0; i < n; i++)    //打印当前组合
        {
            if (pTable[i])
            {
                combin[k] = data[i];
                //cout << data[i] << "\t";
                k+=1;
            }
        }
       CardCombin.push_back(combin);
       //cout << endl;

        bFind = false;
        for (uint16_t i = 0; i < n - 1; i++)
        {
            if (pTable[i] == 1 && pTable[i + 1] == 0)
            {
                swap(pTable[i], pTable[i + 1]); //调换10为01
                bFind = true;

                if (pTable[0] == 0) //如果第一位为0，则将第i位置之前的1移到最左边，如为1则第i位置之前的1就在最左边，无需移动
                {
                    for (uint16_t k = 0, j = 0; k < i; k++) //O(n)复杂度使1在前0在后
                    {
                        if (pTable[k])
                        {
                            swap(pTable[k], pTable[j]);
                            j++;
                        }
                    }
                }

                break;
            }
        }
    } while (bFind);

    delete[] pTable;

}

// void printResult(vector<uint32_t> &vecInt, vector<uint32_t> &data)
// {
//     uint32_t *combin = new uint32_t(2);
//     uint32_t k = 0;
//     for (uint32_t i = 0; i < vecInt.size(); ++i)
//     {

//         if (vecInt[i] == 1)
//         {
//             combin[k] = data[i];
//            // cout << combin[k] << "\t";
//             k+=1;
//         }
//     }
//    // cout << endl;
//     CardCombin.push_back(combin);        

// }

// bool compare(uint32_t a, uint32_t b)
// {
//     if (a > b)
//     {
//         return true;
//     }
//     else
//     {
//         return false;
//     }
// }

// void combination(vector<uint32_t> &data, uint32_t c, uint32_t total)
// {
//     //初始第一组合:1,1,0,0,0....
//     vector<uint32_t> vecInt(total, 0);
//     for (uint32_t i = 0; i < c; ++i)
//     {
//         vecInt[i] = 1;
//     }

//     printResult(vecInt, data);

//     for (uint32_t i = 0; i < total - 1; ++i)
//     {
//         if (vecInt[i] == 1 && vecInt[i + 1] == 0)
//         {
//             //1. 第一交换1和0到0 0
//             swap(vecInt[i], vecInt[i + 1]);

//             //2.移动所有的一到vecInt的左边
//             sort(vecInt.begin(), vecInt.begin() + i, compare);

//             //在步骤1和步骤2之后，存在新的组合。
//             printResult(vecInt, data);
//             //尝试从前面执行步骤1和步骤2
//             i = -1;
//         }
//     }
// }

int main()
{
    std::map<uint32_t, string> m_mapBountyGroup;
    std::vector<uint16_t> data;
    for (uint8_t i = 1; i < 14; i++)
    {
        data.push_back(SETC_COLPOI(4, i));
        data.push_back(SETC_COLPOI(3, i));
        data.push_back(SETC_COLPOI(2, i));
        data.push_back(SETC_COLPOI(1, i));
       // data.push_back(i);
    }

    std::cout << "开始前：" << time(0) << endl;
    Combine(data, TOTAL, NUM);

//     a[0] = NUM;
//    comb(TOTAL, NUM); //TOTAL中NUM的组合

    //combination(data, NUM, TOTAL);

    std::cout << "开始后：" << time(0) << endl;
    std::cout << "个数：" << CardCombin.size() << endl;
    std::vector<uint16_t *>::iterator iter, ei = CardCombin.end();
    for (iter = CardCombin.begin(); iter!=ei; ++iter)
       // for (uint32_t i = 0; i < CardCombin.size(); ++i)
    {
        for (uint16_t j = 0; j < NUM; j++)
        {
            //std::cout << (*iter)[j] << "\t";
            if (GETC_POINT((*iter)[0]) == GETC_POINT((*iter)[1]) == GETC_POINT((*iter)[2]) == GETC_POINT((*iter)[3]))
                std::cout << "color：" << GETC_COLOR((*iter)[j]) << "     point: " << GETC_POINT((*iter)[j]) << endl;
        }
       // std::cout << std::endl;
    }
    return 0;
}


